package com.hugang.communication;

/**
 * 线程通信举例：使用两个线程打印1-100，线程1、2交替打印
 *
 * 涉及三个方法：
 * wait(): 一旦执行此方法，当前线程就会进入阻塞状态，并释放同步监视器
 * notify(): 一旦执行此方法，就会唤醒被wait()的一个线程，若有多个线程被wait()，则唤醒优先级高的线程
 * notifyAll(): 一旦执行此方法，就会唤醒所有被wait()的线程
 *
 * 说明：
 * 1、以上三个方法必须使用在同步代码块或同步方法中（不能放在lock代码块中）
 * 2、以上三个方法的调用者必须是同步代码块或同步方法中的同步监视器，否则会出现IllegalMonitorStateException异常。
 * 3、以上三个方法是定义在java.lang.Object类中的（原因：任何对象都可以充当同步监视器，而这三个方法又必须是同步监视器调用）
 *
 * 面试题：sleep()和wait()方法的异同？
 * 1、相同点：一旦执行，都可以使得当前线程进入阻塞状态
 * 2、不同的：
 *      a、方法声明的位置不一样：Thread类中的静态的sleep(),Object类中的wait()
 *      b、调用要求不同：sleep()可以在任何场景调用，而wait()必须使用在同步代码块或同步方法中
 *      c、如果两种都使用在同步代码块或同步方法中，sleep()不会释放锁，而wait()会释放锁
 * @author hg
 * @date 2020/6/16 09:13
 */
public class CommunicationTest {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);

        t1.setName("线程1");
        t2.setName("线程2");

        t1.start();
        t2.start();
    }


}

class Number implements Runnable {
    private int number = 1;
    Object object = new Object();

    @Override
    public void run() {

        while (true) {

            synchronized (object) {
//            synchronized (this) {
                object.notify();
//                this.notify();

                if (number <= 100) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":打印数字:" + number++);

                    try {
                        object.wait();
//                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}
